// -*- mode:c++ -*-

// Copyright (c) 2009 The University of Edinburgh
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Timothy M. Jones

////////////////////////////////////////////////////////////////////
//
// The actual Power ISA decoder
// ------------------------------
//
// I've used the Power ISA Book I v2.06 for instruction formats,
// opcode numbers, register names, etc.
//
decode OPCODE default Unknown::unknown() {

    format IntImmOp {
        10: cmpli({{
            Xer xer = XER;
            uint32_t cr = makeCRField(Ra, (uint32_t)uimm, xer.so);
            CR = insertCRField(CR, BF, cr);
            }});
        11: cmpi({{
            Xer xer = XER;
            uint32_t cr = makeCRField(Ra_sw, (int32_t)imm, xer.so);
            CR = insertCRField(CR, BF, cr);
            }});
    }

    // Some instructions use bits 21 - 30, others 22 - 30. We have to use
    // the larger size to account for all opcodes. For those that use the
    // smaller value, the OE bit is bit 21. Therefore, we have two versions
    // of each instruction: 1 with OE set, the other without. For an
    // example see 'add' and 'addo'.
    31: decode XO_XO {

        // These instructions can all be reduced to the form
        // Rt = src1 + src2 [+ CA], therefore we just give src1 and src2
        // (and, if necessary, CA) definitions and let the python script
        // deal with setting things up correctly. We also give flags to
        // say which control registers to set.
        format IntSumOp {
            266: add({{ Ra }}, {{ Rb }});
            40: subf({{ ~Ra }}, {{ Rb }}, {{ 1 }});
            10: addc({{ Ra }}, {{ Rb }},
                     computeCA = true);
            8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }},
                     true);
            104: neg({{ ~Ra }}, {{ 1 }});
            138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }},
                      true);
            234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
                       true);
            136: subfe({{ ~Ra }}, {{ Rb }}, {{ xer.ca }},
                       true);
            232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
                        true);
            202: addze({{ Ra }}, {{ xer.ca }},
                       computeCA = true);
            200: subfze({{ ~Ra }}, {{ xer.ca }},
                        computeCA = true);
        }

        // Arithmetic instructions all use source registers Ra and Rb,
        // with destination register Rt.
        format IntArithOp {
            75: mulhw({{ int64_t prod = Ra_sq * Rb_sq; Rt = prod >> 32; }});
            11: mulhwu({{ uint64_t prod = Ra_uq * Rb_uq; Rt = prod >> 32; }});
            235: mullw({{ int64_t prod = Ra_sq * Rb_sq; Rt = prod; }});
            747: mullwo({{ int64_t src1 = Ra_sq; int64_t src2 = Rb; int64_t prod = src1 * src2; Rt = prod; }},
                        true);

            491: divw({{
                int32_t src1 = Ra_sw;
                int32_t src2 = Rb_sw;
                if ((src1 != 0x80000000 || src2 != 0xffffffff)
                    && src2 != 0) {
                    Rt = src1 / src2;
                } else {
                    Rt = 0;
                }
            }});

            1003: divwo({{
                int32_t src1 = Ra_sw;
                int32_t src2 = Rb_sw;
                if ((src1 != 0x80000000 || src2 != 0xffffffff)
                    && src2 != 0) {
                    Rt = src1 / src2;
                } else {
                    Rt = 0;
                    divSetOV = true;
                }
            }},
            true);

            459: divwu({{
                uint32_t src1 = Ra_sw;
                uint32_t src2 = Rb_sw;
                if (src2 != 0) {
                    Rt = src1 / src2;
                } else {
                    Rt = 0;
                }
            }});

            971: divwuo({{
              uint32_t src1 = Ra_sw;
              uint32_t src2 = Rb_sw;
              if (src2 != 0) {
                  Rt = src1 / src2;
              } else {
                  Rt = 0;
                  divSetOV = true;
              }
            }},
            true);
        }

        // Integer logic instructions use source registers Rs and Rb,
        // with destination register Ra.
        format IntLogicOp {
            28: and({{ Ra = Rs & Rb; }});
            316: xor({{ Ra = Rs ^ Rb; }});
            476: nand({{ Ra = ~(Rs & Rb); }});
            444: or({{ Ra = Rs | Rb; }});
            124: nor({{ Ra = ~(Rs | Rb); }});
            60: andc({{ Ra = Rs & ~Rb; }});
            954: extsb({{ Ra = sext<8>(Rs); }});
            284: eqv({{ Ra = ~(Rs ^ Rb); }});
            412: orc({{ Ra = Rs | ~Rb; }});
            922: extsh({{ Ra = sext<16>(Rs); }});
            26: cntlzw({{ Ra = Rs == 0 ? 32 : 31 - findMsbSet(Rs); }});
            508: cmpb({{
                uint32_t val = 0;
                for (int n = 0; n < 32; n += 8) {
                    if(bits(Rs, n+7, n) == bits(Rb, n+7, n)) {
                        val = insertBits(val, n+7, n, 0xff);
                    }
                }
                Ra = val;
            }});

            24: slw({{
                if (Rb & 0x20) {
                    Ra = 0;
                } else {
                    Ra = Rs << (Rb & 0x1f);
                }
            }});

            536: srw({{
                if (Rb & 0x20) {
                    Ra = 0;
                } else  {
                    Ra = Rs >> (Rb & 0x1f);
                }
            }});

            792: sraw({{
                bool shiftSetCA = false;
                int32_t s = Rs;
                if (Rb == 0) {
                    Ra = Rs;
                    shiftSetCA = true;
                } else if (Rb & 0x20) {
                    if (s < 0) {
                        Ra = (uint32_t)-1;
                        if (s & 0x7fffffff) {
                            shiftSetCA = true;
                        } else {
                            shiftSetCA = false;
                        }
                    } else {
                        Ra = 0;
                        shiftSetCA = false;
                    }
                } else {
                    Ra = s >> (Rb & 0x1f);
                    if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) {
                        shiftSetCA = true;
                    } else {
                        shiftSetCA = false;
                    }
                }
                Xer xer1 = XER;
                if (shiftSetCA) {
                    xer1.ca = 1;
                } else {
                    xer1.ca = 0;
                }
                XER = xer1;
            }});
        }

        // Integer logic instructions with a shift value.
        format IntShiftOp {
            824: srawi({{
                bool shiftSetCA = false;
                if (sh == 0) {
                    Ra = Rs;
                    shiftSetCA = false;
                } else {
                    int32_t s = Rs;
                    Ra = s >> sh;
                    if (s < 0 && (s << (32 - sh)) != 0) {
                        shiftSetCA = true;
                    } else {
                        shiftSetCA = false;
                    }
                }
                Xer xer1 = XER;
                if (shiftSetCA) {
                    xer1.ca = 1;
                } else {
                    xer1.ca = 0;
                }
                XER = xer1;
            }});
        }

        // Generic integer format instructions.
        format IntOp {
            0: cmp({{
                Xer xer = XER;
                uint32_t cr = makeCRField(Ra_sw, Rb_sw, xer.so);
                CR = insertCRField(CR, BF, cr);
                }});
            32: cmpl({{
                Xer xer = XER;
                uint32_t cr = makeCRField(Ra, Rb, xer.so);
                CR = insertCRField(CR, BF, cr);
                }});
            144: mtcrf({{
                uint32_t mask = 0;
                for (int i = 0; i < 8; ++i) {
                    if (((FXM >> i) & 0x1) == 0x1) {
                        mask |= 0xf << (4 * i);
                    }
                }
                CR = (Rs & mask) | (CR & ~mask);
                }});
            19: mfcr({{ Rt = CR; }});
            339: decode SPR {
                0x20: mfxer({{ Rt = XER; }});
                0x100: mflr({{ Rt = LR; }});
                0x120: mfctr({{ Rt = CTR; }});
            }
            467: decode SPR {
                0x20: mtxer({{ XER = Rs; }});
                0x100: mtlr({{ LR = Rs; }});
                0x120: mtctr({{ CTR = Rs; }});
            }
        }

        // All loads with an index register. The non-update versions
        // all use the value 0 if Ra == R0, not the value contained in
        // R0. Others update Ra with the effective address. In all cases,
        // Ra and Rb are source registers, Rt is the destintation.
        format LoadIndexOp {
            87: lbzx({{ Rt = Mem_ub; }});
            279: lhzx({{ Rt = Mem_uh; }});
            343: lhax({{ Rt = Mem_sh; }});
            23: lwzx({{ Rt = Mem; }});
            341: lwax({{ Rt = Mem_sw; }});
            20: lwarx({{ Rt = Mem_sw; Rsv = 1; RsvLen = 4; RsvAddr = EA; }});
            535: lfsx({{ Ft_sf = Mem_sf; }});
            599: lfdx({{ Ft = Mem_df; }});
            855: lfiwax({{ Ft_uw = Mem; }});
        }

        format LoadIndexUpdateOp {
            119: lbzux({{ Rt = Mem_ub; }});
            311: lhzux({{ Rt = Mem_uh; }});
            375: lhaux({{ Rt = Mem_sh; }});
            55: lwzux({{ Rt = Mem; }});
            373: lwaux({{ Rt = Mem_sw; }});
            567: lfsux({{ Ft_sf = Mem_sf; }});
            631: lfdux({{ Ft = Mem_df; }});
        }

        format StoreIndexOp {
            215: stbx({{ Mem_ub = Rs_ub; }});
            407: sthx({{ Mem_uh = Rs_uh; }});
            151: stwx({{ Mem = Rs; }});
            150: stwcx({{
                bool store_performed = false;
                Mem = Rs;
                if (Rsv) {
                    if (RsvLen == 4) {
                        if (RsvAddr == EA) {
                            store_performed = true;
                        }
                    }
                }
                Xer xer = XER;
                Cr cr = CR;
                cr.cr0 = ((store_performed ? 0x2 : 0x0) | xer.so);
                CR = cr;
                Rsv = 0;
            }});
            663: stfsx({{ Mem_sf = Fs_sf; }});
            727: stfdx({{ Mem_df = Fs; }});
            983: stfiwx({{ Mem = Fs_uw; }});
        }

        format StoreIndexUpdateOp {
            247: stbux({{ Mem_ub = Rs_ub; }});
            439: sthux({{ Mem_uh = Rs_uh; }});
            183: stwux({{ Mem = Rs; }});
            695: stfsux({{ Mem_sf = Fs_sf; }});
            759: stfdux({{ Mem_df = Fs; }});
        }

        // These instructions all provide data cache hints
        format MiscOp {
            278: dcbt({{ }});
            246: dcbtst({{ }});
            598: sync({{ }}, [ IsMemBarrier ]);
            854: eieio({{ }}, [ IsMemBarrier ]);
        }
    }

    format IntImmArithCheckRaOp {
        14: addi({{ Rt = Ra + imm; }},
                 {{ Rt = imm }});
        15: addis({{ Rt = Ra + (imm << 16); }},
                  {{ Rt = imm << 16; }});
    }

    format IntImmArithOp {
        12: addic({{ uint32_t src = Ra; Rt = src + imm; }},
                  [computeCA]);
        13: addic_({{ uint32_t src = Ra; Rt = src + imm; }},
                   [computeCA, computeCR0]);
        8: subfic({{ int32_t src = ~Ra; Rt = src + imm + 1; }},
                  [computeCA]);
        7: mulli({{
            int32_t src = Ra_sw;
            int64_t prod = src * imm;
            Rt = (uint32_t)prod;
        }});
    }

    format IntImmLogicOp {
        24: ori({{ Ra = Rs | uimm; }});
        25: oris({{ Ra = Rs | (uimm << 16); }});
        26: xori({{ Ra = Rs ^ uimm; }});
        27: xoris({{ Ra = Rs ^ (uimm << 16); }});
        28: andi_({{ Ra = Rs & uimm; }},
                  true);
        29: andis_({{ Ra = Rs & (uimm << 16); }},
                   true);
    }

    16: decode AA {

        // Conditionally branch relative to PC based on CR and CTR.
        format BranchPCRelCondCtr {
            0: bc({{ NPC = (uint32_t)(PC + disp); }});
        }

        // Conditionally branch to fixed address based on CR and CTR.
        format BranchNonPCRelCondCtr {
            1: bca({{ NPC = targetAddr; }});
        }
    }

    18: decode AA {

        // Unconditionally branch relative to PC.
        format BranchPCRel {
            0: b({{ NPC = (uint32_t)(PC + disp); }});
        }

        // Unconditionally branch to fixed address.
        format BranchNonPCRel {
            1: ba({{ NPC = targetAddr; }});
        }
    }

    19: decode XO_XO {

        // Conditionally branch to address in LR based on CR and CTR.
        format BranchLrCondCtr {
           16: bclr({{ NPC = LR & 0xfffffffc; }});
        }

        // Conditionally branch to address in CTR based on CR.
        format BranchCtrCond {
           528: bcctr({{ NPC = CTR & 0xfffffffc; }});
        }

        // Condition register manipulation instructions.
        format CondLogicOp {
            257: crand({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa & crBb);
            }});
            449: cror({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa | crBb);
            }});
            255: crnand({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, !(crBa & crBb));
            }});
            193: crxor({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa ^ crBb);
            }});
            33: crnor({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, !(crBa | crBb));
            }});
            289: creqv({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa == crBb);
            }});
            129: crandc({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa & !crBb);
            }});
            417: crorc({{
                uint32_t crBa = bits(CR, 31 - ba);
                uint32_t crBb = bits(CR, 31 - bb);
                CR = insertBits(CR, 31 - bt, crBa | !crBb);
            }});
        }
        format CondMoveOp {
            0: mcrf({{
                uint32_t crBfa = bits(CR, 31 - bfa*4, 28 - bfa*4);
                CR = insertBits(CR, 31 - bf*4, 28 - bf*4, crBfa);
            }});
        }
        format MiscOp {
            150: isync({{ }}, [ IsSerializeAfter ]);
        }
    }

    format IntRotateOp {
        21: rlwinm({{ Ra = rotateValue(Rs, sh) & fullMask; }});
        23: rlwnm({{ Ra = rotateValue(Rs, Rb) & fullMask; }});
        20: rlwimi({{ Ra = (rotateValue(Rs, sh) & fullMask) | (Ra & ~fullMask); }});
    }

    format LoadDispOp {
        34: lbz({{ Rt = Mem_ub; }});
        40: lhz({{ Rt = Mem_uh; }});
        42: lha({{ Rt = Mem_sh; }});
        32: lwz({{ Rt = Mem; }});
        58: lwa({{ Rt = Mem_sw; }},
                {{ EA = Ra + (disp & 0xfffffffc); }},
                {{ EA = disp & 0xfffffffc; }});
        48: lfs({{ Ft_sf = Mem_sf; }});
        50: lfd({{ Ft = Mem_df; }});
    }

    format LoadDispUpdateOp {
        35: lbzu({{ Rt = Mem_ub; }});
        41: lhzu({{ Rt = Mem_uh; }});
        43: lhau({{ Rt = Mem_sh; }});
        33: lwzu({{ Rt = Mem; }});
        49: lfsu({{ Ft_sf = Mem_sf; }});
        51: lfdu({{ Ft = Mem_df; }});
    }

    format StoreDispOp {
        38: stb({{ Mem_ub = Rs_ub; }});
        44: sth({{ Mem_uh = Rs_uh; }});
        36: stw({{ Mem = Rs; }});
        52: stfs({{ Mem_sf = Fs_sf; }});
        54: stfd({{ Mem_df = Fs; }});
    }

    format StoreDispUpdateOp {
        39: stbu({{ Mem_ub = Rs_ub; }});
        45: sthu({{ Mem_uh = Rs_uh; }});
        37: stwu({{ Mem = Rs; }});
        53: stfsu({{ Mem_sf = Fs_sf; }});
        55: stfdu({{ Mem_df = Fs; }});
    }

    17: IntOp::sc({{ xc->syscall(R0, &fault); }},
                  [ IsSyscall, IsNonSpeculative, IsSerializeAfter ]);

    format FloatArithOp {
        59: decode A_XO {
            21: fadds({{ Ft = Fa + Fb; }});
            20: fsubs({{ Ft = Fa - Fb; }});
            25: fmuls({{ Ft = Fa * Fc; }});
            18: fdivs({{ Ft = Fa / Fb; }});
            29: fmadds({{ Ft = (Fa * Fc) + Fb; }});
            28: fmsubs({{ Ft = (Fa * Fc) - Fb; }});
            31: fnmadds({{ Ft = -((Fa * Fc) + Fb); }});
            30: fnmsubs({{ Ft = -((Fa * Fc) - Fb); }});
        }
    }

    63: decode A_XO {
        format FloatArithOp {
            21: fadd({{ Ft = Fa + Fb; }});
            20: fsub({{ Ft = Fa - Fb; }});
            25: fmul({{ Ft = Fa * Fc; }});
            18: fdiv({{ Ft = Fa / Fb; }});
            29: fmadd({{ Ft = (Fa * Fc) + Fb; }});
            28: fmsub({{ Ft = (Fa * Fc) - Fb; }});
            31: fnmadd({{ Ft = -((Fa * Fc) + Fb); }});
            30: fnmsub({{ Ft = -((Fa * Fc) - Fb); }});
        }

        default: decode XO_XO {
            format FloatConvertOp {
                12: frsp({{ Ft_sf = Fb; }});
                15: fctiwz({{ Ft_sw = (int32_t)trunc(Fb); }});
            }

            format FloatOp {
              0: fcmpu({{
                  uint32_t c = makeCRField(Fa, Fb);
                  Fpscr fpscr = FPSCR;
                  fpscr.fprf.fpcc = c;
                  FPSCR = fpscr;
                  CR = insertCRField(CR, BF, c);
              }});
            }

            format FloatRCCheckOp {
                72: fmr({{ Ft = Fb; }});
                264: fabs({{
                    Ft_uq = Fb_uq;
                    Ft_uq = insertBits(Ft_uq, 63, 0); }});
                136: fnabs({{
                    Ft_uq = Fb_uq;
                    Ft_uq = insertBits(Ft_uq, 63, 1); }});
                40: fneg({{ Ft = -Fb; }});
                8: fcpsgn({{
                    Ft_uq = Fb_uq;
                    Ft_uq = insertBits(Ft_uq, 63, Fa_uq<63:63>);
                }});
                583: mffs({{ Ft_uq = FPSCR; }});
                134: mtfsfi({{
                    FPSCR = insertCRField(FPSCR, BF + (8 * (1 - W_FIELD)),
                                          U_FIELD);
                }});
                711: mtfsf({{
                    if (L_FIELD == 1) { FPSCR = Fb_uq; }
                    else {
                        for (int i = 0; i < 8; ++i) {
                            if (bits(FLM, i) == 1) {
                                int k = 4 * (i + (8 * (1 - W_FIELD)));
                                FPSCR = insertBits(FPSCR, k + 3, k,
                                                   bits(Fb_uq, k + 3, k));
                            }
                        }
                    }
                }});
                70: mtfsb0({{ FPSCR = insertBits(FPSCR, 31 - BT, 0); }});
                38: mtfsb1({{ FPSCR = insertBits(FPSCR, 31 - BT, 1); }});
            }
        }
    }
}
